import requests
import json
import hmac
import hashlib
import time
import os
from ..exceptions import PlatformAPIException, PlatformRequestException, PlatformNotSupportSymbolException, PlatformHighRateException
from ..restapibase import RestAPIBase
from MarketData.const import CONST
from .symbols import symbols


class HitbtcRESTAPI(RestAPIBase):
    """docstring for BinanceRESTAPI"""

    def __init__(self, api_key, secret_key, isdebug=False):
        self.api_key = api_key
        self.secret_key = secret_key
        self.isdebug = isdebug
        self.url = 'https://api.hitbtc.com'
        self.session = requests.session()
        self.session.auth = (api_key, secret_key)

    def _debug(self, result):
        if self.isdebug:
            print(result)

    def _get(self, endpoint, params={}):
        url = self.url + endpoint

        response = self.session.get(url, params=params)
        self._debug(response.text)

        rescode = response.status_code
        errmsg = 'StatusCode: GET %s \nURL:%s \nParams: %s \nResponse: %s' % (
            response.status_code, url, str(params), response.text)
        response = response.json()

        if response or rescode == 200:
            if rescode == 200:
                return response
            elif rescode == 429:
                raise PlatformHighRateException(errmsg)
            else:
                raise PlatformAPIException(errmsg)
        else:
            raise PlatformRequestException(errmsg)

    def _del(self, endpoint, params={}):
        url = self.url + endpoint

        response = self.session.delete(url, params=params)
        self._debug(response.text)

        rescode = response.status_code
        errmsg = 'StatusCode: DELETE %s \nURL:%s \nParams: %s \nResponse: %s' % (
            response.status_code, url, str(params), response.text)
        response = response.json()

        if response or rescode == 200:
            if rescode == 200:
                return response
            elif rescode == 429:
                raise PlatformHighRateException(errmsg)
            else:
                raise PlatformAPIException(errmsg)
        else:
            raise PlatformRequestException(errmsg)

    def _post(self, endpoint, data={}):
        url = self.url + endpoint

        response = self.session.post(url, data=data)
        self._debug(response.text)

        rescode = response.status_code
        errmsg = 'StatusCode: POST %s \nURL:%s \nData: %s \nResponse: %s' % (
            response.status_code, url, str(data), response.text)
        response = response.json()

        if response or rescode == 200:
            if rescode == 200:
                return response
            elif rescode == 429:
                raise PlatformHighRateException(errmsg)
            else:
                raise PlatformAPIException(errmsg)
        else:
            raise PlatformRequestException(errmsg)

    # EndPoints
    def _symbols(self):
        url = '/api/2/public/symbol'

        resjson = self._get(url)
        self._debug('symbols: \n' + json.dumps(resjson, indent=2))

        result = []
        for res in resjson:
            result.append(res['id'])
        sw = open(os.path.dirname(
            os.path.realpath(__file__)) + '/symbols.py', 'w')
        sw.write('symbols = ' + str(result))
        sw.close()
        self._debug('symbols: \n' + str(result))

        return result

    def _order(self, symbol, side, ordertype, amount, price):
        url = '/api/2/order'

        data = {
            'symbol': symbol,
            'side': side,
            'type': ordertype,
            'quantity': amount,
        }

        if ordertype.lower() == 'market':
            data['timeInForce'] = 'FOK'
        elif ordertype.lower() == 'limit':
            data['price'] = price

        result = self._post(url, data)
        return result

    # Public
    def get_currency(self, currency):
        if currency.upper() == 'USDT':
            currency = 'USD'

        return currency.upper()

    def get_symbol(self, commodity, base):
        if commodity.upper() == 'USDT':
            commodity = 'USD'
        if base.upper() == 'USDT':
            base = 'USD'

        result = commodity.upper() + base.upper()

        if not (result in symbols):
            errmsg = 'Not supported: %s' % result
            raise PlatformNotSupportSymbolException(errmsg)

        return result

    def get_ticker(self, symbol):
        url = '/api/2/public/ticker' + symbol

        result = self._get(url)
        self._debug('ticker: \n' + json.dumps(result, indent=2))
        return result

    def get_depth(self, symbol):
        url = '/api/2/public/orderbook/' + symbol

        resjson = self._get(url)
        result = {}
        self._debug('get_depth: \n' + json.dumps(resjson, indent=2))

        bids = [{'price': bid['price'], 'amount': bid['size']}
                for bid in resjson['bid']]
        asks = [{'price': ask['price'], 'amount': ask['size']}
                for ask in resjson['ask']]
        result = {'bids': bids, 'asks': asks}

        self._debug('get_depth: \n' + json.dumps(result, indent=2))
        return result

    # NotImplementedError
    def get_account(self):
        raise NotImplementedError()

    def get_balances(self, type='trade'):
        url = '/api/2/trading/balance'

        resjson = self._get(url)
        result = {}
        for balance in resjson:
            result[balance['currency']] = float(balance['available'])

        self._debug('ticker: \n' + json.dumps(result, indent=2))
        return result

    def limit_buy(self, symbol, amount, price):
        resjson = self._order(symbol, 'buy', 'limit', amount, price)
        result = {"id": resjson["clientOrderId"]}
        self._debug('limit_buy: \n' + json.dumps(result, indent=2))
        return result

    def limit_sell(self, symbol, amount, price):
        resjson = self._order(symbol, 'sell', 'limit', amount, price)
        result = {"id": resjson["clientOrderId"]}
        self._debug('limit_sell: \n' + json.dumps(result, indent=2))
        return result

    def market_buy(self, symbol, amount, price=None):
        resjson = self._order(symbol, 'buy', 'limit', amount, "%.7f" % (
            float(price) * (1 + CONST.Slippage_synMarket)))
        result = {"id": resjson["clientOrderId"]}

        self._debug('market_buy: \n' + json.dumps(result, indent=2))
        return result

    def market_sell(self, symbol, amount, price=None):
        resjson = self._order(symbol, 'sell', 'limit', amount, "%.7f" % (
            float(price) * (1 - CONST.Slippage_synMarket)))
        result = {"id": resjson["clientOrderId"]}

        self._debug('market_sell: \n' + json.dumps(result, indent=2))
        return result

    # NotImplementedError
    def get_order(self, order_id):
        raise NotImplementedError()

    # NotImplementedError
    def get_all_orders(self):
        raise NotImplementedError()

    def get_open_orders(self):
        url = '/api/2/order'

        result = self._get(url)
        self._debug('get_open_orders: \n' + json.dumps(result, indent=2))
        return result

    # NotImplementedError
    def cancel_order(self, order_id):
        raise NotImplementedError()

    def cancel_all_orders(self):
        url = '/api/2/order'

        resjson = self._del(url)
        self._debug('cancel_all_orders: \n' + json.dumps(resjson, indent=2))

        result = True
        for res in resjson:
            if res['status'] != 'canceled':
                result = False
                return result
        return result

    def withdraw(self, currency, amount, address):
        url = '/api/2/account/crypto/withdraw'
        data = {
            "amount": amount,
            "currency": currency,
            "address": address,
        }

        result = self._post(url, data)
        self._debug('withdraw: \n' + json.dumps(result, indent=2))
        return result
